// @ts-nocheck
import React, { createContext, useContext } from "react";
import { Button, ButtonProps } from "antd";
import {
    DeleteOutlined,
    DownOutlined,
    UpOutlined,
    UploadOutlined,
    PlusOutlined,
    MenuOutlined,
    EditOutlined,
    CopyOutlined,
    EyeOutlined,
    SnippetsOutlined,
    DeleteRowOutlined,
    ExportOutlined,
} from "@ant-design/icons";
import { AntdIconProps } from "@ant-design/icons/lib/components/AntdIcon";

import { useField, useFieldSchema, Schema, JSXComponent } from "@formily/react";
import { isValid } from "@formily/shared";
import { SortableHandle } from "react-sortable-hoc";
import { usePrefixCls } from "./usePrefixCls";
import cls from "classnames";

import { toJS } from "@formily/reactive";

export interface IArrayBaseAdditionProps extends ButtonProps {
    title?: string;
    method?: "push" | "unshift";
    defaultValue?: any;
    [key: string]: any;
}

export interface IArrayBaseContext {
    props: IArrayBaseProps;
    field: any;
    schema: Schema;
}

export interface IArrayBaseItemProps {
    index: number;
}

export interface IArrayButtonEventProps {
    onValueChange?: () => void;
    onBatchDelete?: () => void;
}

export type ArrayBaseMixins = {
    Addition?: React.FC<IArrayBaseAdditionProps>;
    Remove?: React.FC<AntdIconProps & { index?: number }>;
    MoveUp?: React.FC<AntdIconProps & { index?: number }>;
    MoveDown?: React.FC<AntdIconProps & { index?: number }>;
    Detail?: React.FC<AntdIconProps & { index?: number }>;
    EditOut?: React.FC<AntdIconProps & { index?: number }>;
    Copy?: React.FC<AntdIconProps & { index?: number }>;
    SortHandle?: React.FC<AntdIconProps & { index?: number }>;
    Delete?: React.FC<IArrayBaseAdditionProps & { index?: number }>;
    OpenLib?: React.FC<IArrayBaseAdditionProps & { index?: number }>;
    Preview?: React.FC<IArrayBaseAdditionProps & { index?: number }>;
    Export?: React.FC<IArrayBaseAdditionProps & { index?: number }>;
    Upload?: React.FC<IArrayBaseAdditionProps & { index?: number }>;
    DownOut?: React.FC<IArrayBaseAdditionProps & { index?: number }>;
    SalerWtdwl?: React.FC<IArrayBaseAdditionProps & { index?: number }>;
    Index?: React.FC;
    useArray?: () => IArrayBaseContext;
    useIndex?: () => number;
};

export interface IArrayBaseProps {
    disabled?: boolean;
    onAdd?: (index: number) => void;
    onRemove?: (index: number) => void;
    onMoveDown?: (index: number) => void;
    onMoveUp?: (index: number) => void;
    onCopy?: (index: number) => void;
    onEditOut?: (index: number, col: any) => void;
    onValueChange?: () => any;
    onBatchDelete?: (array: any) => void;
    onPreview?: () => void;
    onImport?: () => void;
    onOpenLib: () => void;
    onLogic: () => void;
    disabledIndex?: number[];
    onTravel: () => void;
    [key: string]: any;
}

type ComposedArrayBase = React.FC<IArrayBaseProps> &
    ArrayBaseMixins & {
    Item?: React.FC<IArrayBaseItemProps>;

    mixin?: <T extends JSXComponent>(target: T) => T & ArrayBaseMixins;
};

const ArrayBaseContext = createContext<IArrayBaseContext | null>(null);

const ItemContext = createContext<IArrayBaseItemProps | null>(null);

const useArray = () => {
    return useContext(ArrayBaseContext);
};

const useIndex = (index?: number) => {
    const ctx = useContext(ItemContext);
    return ctx ? ctx.index : index;
};

const getDefaultValue = (defaultValue: any, schema: Schema) => {
    if (isValid(defaultValue)) return defaultValue;
    if (Array.isArray(schema?.items))
        return getDefaultValue(defaultValue, schema.items[0]);
    if (schema?.items?.type === "array") return [];
    if (schema?.items?.type === "boolean") return true;
    if (schema?.items?.type === "date") return "";
    if (schema?.items?.type === "datetime") return "";
    if (schema?.items?.type === "number") return 0;
    if (schema?.items?.type === "object") return {};
    if (schema?.items?.type === "string") return "";
    return null;
};

export const ArrayBase: ComposedArrayBase = (props) => {
    const field = useField<Formily.Core.Models.ArrayField>();
    const schema = useFieldSchema();
    return (
        <ArrayBaseContext.Provider value={{ field, schema, props }}>
            {props.children}
        </ArrayBaseContext.Provider>
    );
};

ArrayBase.Item = ({ children, ...props }) => {
    return <ItemContext.Provider value={props}>{children}</ItemContext.Provider>;
};

const SortHandle = SortableHandle((props: any) => {
    const prefixCls = usePrefixCls("formily-array-base");
    return (
        <MenuOutlined
            {...props}
            className={cls(`${prefixCls}-sort-handle`, props.className)}
            style={{ ...props.style }}
        />
    );
}) as any;

ArrayBase.SortHandle = (props) => {
    const array = useArray();
    const field = useField();
    if (!array) return null;
    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;
    return <SortHandle {...props} />;
};

ArrayBase.Index = (props) => {
    const index = useIndex();
    // 设置自定义的序号
    if (props.custom) {
        if (index < 9) {
            return <span {...props}>{"0" + (index + 1)}</span>;
        } else {
            return <span {...props}>{index + 1}</span>;
        }
    } else {
        return <span {...props}>{index + 1}</span>;
    }
};
ArrayBase.SalerWtdwl = (props: any) => {

    const array = useArray();
    const field = useField();
    if (!array) return null;
    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;
    return (
        <Button
            type="button"
            {...props}
            className={cls("ant-formily-array-btn", props.className)}
            onClick={(e) => {
                if (array.props?.disabled) return;
                if (props?.batchDelete) {
                    props.batchDelete(field, array);
                }
                if (props.onTravel) {
                    props.onTravel(e);
                }
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(e);
                }
            }}
            icon={<DeleteRowOutlined />}
        >
            {props.title || field.title}
        </Button>
    );
};
ArrayBase.Addition = (props) => {
    const field = useField();
    const array = useArray();
    const prefixCls = usePrefixCls("formily-array-base");
    const {
        props: { onValueChange },
    } = useContext(ArrayBaseContext) || { props: {} };
    if (!array) return null;
    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;

    return (
        <Button
            type="button"
            {...props}
            className={cls(`${prefixCls}-addition`, props.className)}
            onClick={(e) => {
                if (array.props?.disabled) return;
                const defaultValue = getDefaultValue(props.defaultValue, array.schema);
                if (props.method === "unshift") {
                    array.field?.unshift?.(defaultValue);
                    array.props?.onAdd?.(0);
                } else if (props?.hook) {
                    props[props.hook]();
                } else {
                    array.field?.push?.(defaultValue);
                    array.props?.onAdd?.(array?.field?.value?.length - 1);
                }
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(e);
                }
                if (props?.onClick) {
                    props.onClick(e);
                }
                onValueChange?.();
            }}
            icon={<PlusOutlined />}
        >
            {props.title || field.title}
        </Button>
    );
};

ArrayBase.Delete = (props) => {
    const field = useField();
    const array = useArray();
    const {
        props: { onBatchDelete },
    } = useContext(ArrayBaseContext) || { props: {} };
    if (!array) return null;
    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;
    return (
        <Button
            type="button"
            {...props}
            className={cls("ant-formily-array-btn", props.className)}
            onClick={(e) => {
                if (array.props?.disabled) return;
                if (props?.onClick) {
                    props.onClick(e);
                }
                if (props?.batchDeleteCb) {
                    props.batchDeleteCb(array.field?.value || []);
                }
                if (onBatchDelete) {
                    onBatchDelete?.(array);
                }
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(array);
                }
            }}
            icon={<DeleteRowOutlined />}
        >
            {props.title || field.title}
        </Button>
    );
};
// 导出
ArrayBase.Export = React.forwardRef((props, ref) => {
    const field = useField();
    // const index = useIndex(props.index);
    const array = useArray();
    // const prefixCls = usePrefixCls('formily-array-base');
    if (!array) return null;
    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;

    return (
        <Button
            type="button"
            {...props}
            style={{ marginBottom: "10px" }}
            className={cls("ant-formily-array-btn", props.className)}
            onClick={(e) => {
                if (array.props?.disabled) return;

                if (props.onImport) {
                    props.onImport(e);
                }
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(e);
                }
            }}
            icon={<ExportOutlined />}
        >
            {props.title || field?.title}
        </Button>
    );
});

// 上传
ArrayBase.Upload = React.forwardRef((props, ref) => {
    // const index = useIndex(props.index);
    const field = useField();
    const array = useArray();
    // const prefixCls = usePrefixCls('formily-array-base');
    if (!array) return null;
    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;
    return (
        <Button
            type="button"
            {...props}
            style={{ marginBottom: "10px" }}
            className={cls("ant-formily-array-btn", props.className)}
            onClick={(e) => {
                if (array.props?.disabled) return;

                if (props.quickImport) {
                    props.quickImport(e);
                }
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(e);
                }
            }}
            icon={<UploadOutlined />}
        >
            {props.title || field?.title}
        </Button>
    );
});

// 导出
ArrayBase.DownOut = React.forwardRef((props, ref) => {
    // const index = useIndex(props.index);
    const field = useField();
    const array = useArray();
    // const prefixCls = usePrefixCls('formily-array-base');
    if (!array) return null;
    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;
    return (
        <Button
            type="button"
            {...props}
            style={{ marginLeft: "10px" }}
            className={cls("ant-formily-array-btn", props.className)}
            onClick={(e) => {
                if (array.props?.disabled) return;

                if (props.downloadTemplate) {
                    props.downloadTemplate(e);
                }
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(e);
                }
            }}
            icon={<DownOutlined />}
        >
            {props.title || field?.title}
        </Button>
    );
});
ArrayBase.OpenLib = (props: any) => {
    const field = useField();
    const array = useArray();
    if (!array) return null;
    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;
    return (
        <Button
            type="button"
            {...props}
            className={cls("ant-formily-array-btn", props.className)}
            onClick={(e) => {
                if (array.props?.disabled) return;
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(e);
                }
                if (props?.onClick) {
                    props.onClick(e);
                }
            }}
            icon={<DeleteRowOutlined />}
        >
            {props.title || field.title}
        </Button>
    );
};

// 获取图片预览
ArrayBase.Preview = React.forwardRef((props: any, ref) => {
    // const index = useIndex(props.index);
    const array = useArray();
    const field = useField();
    const prefixCls = usePrefixCls("formily-array-base");
    if (!array) return null;
    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;
    return (
        <SnippetsOutlined
            {...props}
            className={cls(`${prefixCls}-remove`, props.className)}
            ref={ref}
            onClick={(e) => {
                if (array.props?.disabled) return;
                e.stopPropagation();
                // const arr = array?.field?.value[index as any];
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(e);
                }
                if (props?.onClick) {
                    props.onClick(e);
                }
            }}
        />
    );
});

ArrayBase.Remove = React.forwardRef((props: any, ref) => {
    const index = useIndex(props.index) as number;
    const array = useArray();
    const field = useField();
    const prefixCls = usePrefixCls("formily-array-base");
    if (!array) return null;

    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;
    const {
        props: { onValueChange, disabledIndex },
    } = useContext(ArrayBaseContext) || { props: {} };

    if (disabledIndex?.includes(index)) {
        return null;
    }

    return (
        <DeleteOutlined
            {...props}
            className={cls(`${prefixCls}-remove`, props.className)}
            ref={ref}
            onClick={async (e) => {
                if (array.props?.disabled) return;
                e.stopPropagation();
                const obj: any = array?.field?.value[index as any];
                let needRemove: boolean = true;

                if (props?.removeCb) {
                    needRemove = await props?.removeCb(obj, index);
                }
                needRemove && array?.field?.remove?.(index);
                needRemove && array?.props?.onRemove?.(index);
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(e);
                }
                if (props?.onClick) {
                    props?.onClick(e);
                }
                onValueChange?.();
            }}
        />
    );
});

/*设置复制按钮*/
ArrayBase.Copy = React.forwardRef((props, ref) => {
    const index = useIndex(props.index);
    const array = useArray();
    const field = useField();
    const prefixCls = usePrefixCls("formily-array-base");
    if (!array) return null;

    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;
    return (
        <CopyOutlined
            {...props}
            className={cls(`${prefixCls}-move-copy`, props.className)}
            ref={ref}
            onClick={(e) => {
                if (array.props?.disabled) return;
                const defaultValue = getDefaultValue(props.defaultValue, array.schema);
                if (props?.copyHook) {
                    props?.copyHook && props?.copyHook(array, index, defaultValue);
                    return;
                }
                if (props.method === "unshift") {
                    array.field?.unshift?.(defaultValue);
                    array.props?.onAdd?.(0);
                } else {
                    array.field?.push?.(array?.field?.value[index as any]);
                    array.props?.onAdd?.(array?.field?.value?.length - 1);
                }
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(e);
                }
                if (props?.onClick) {
                    props.onClick(e);
                }
            }}
        />
    );
});

ArrayBase.Detail = React.forwardRef((props: any, ref) => {
    const index = useIndex(props.index);
    const array = useArray();
    const prefixCls = usePrefixCls("formily-array-base");
    if (!array) return null;
    // fix: 详情按钮在编辑状态不过滤
    // if (array.field?.pattern !== 'editable') return null;
    return (
        <EyeOutlined
            {...props}
            className={cls(`${prefixCls}-move-down`, props.className)}
            ref={ref}
            onClick={(e) => {
                debugger
                if (array.props?.disabled) return;
                e.stopPropagation();

                if (props?.onClick) {
                    const data = toJS(array.field?.value);

                    props.onClick(e, index, data);
                }
                if (props.previewInvoice) {
                    const data = toJS(array.field?.value);

                    props.previewInvoice(e, index, data);
                }
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(e);
                }
            }}
        />
    );
});

ArrayBase.EditOut = React.forwardRef((props, ref) => {
    // const index = useIndex(props.index);
    const array = useArray();
    const field = useField();
    const prefixCls = usePrefixCls("formily-array-base");
    if (!array) return null;
    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;
    return (
        <EditOutlined
            {...props}
            className={cls(`${prefixCls}-move-down`, props.className)}
            ref={ref}
            onClick={(e) => {
                if (array.props?.disabled) return;
                e.stopPropagation();
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(e);
                }
                if (props?.onClick) {
                    props.onClick(e);
                }
            }}
        />
    );
});

ArrayBase.MoveDown = React.forwardRef((props, ref) => {
    const index = useIndex(props.index);
    const array = useArray();
    const prefixCls = usePrefixCls("formily-array-base");
    if (!array) return null;
    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;
    return (
        <DownOutlined
            {...props}
            className={cls(`${prefixCls}-move-down`, props.className)}
            ref={ref}
            onClick={(e) => {
                if (array.props?.disabled) return;
                e.stopPropagation();
                array.field?.moveDown?.(index);
                array.props?.onMoveDown?.(index);
                if (props?.onClick) {
                    props.onClick(e);
                }
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(e);
                }
            }}
        />
    );
});

ArrayBase.MoveUp = React.forwardRef((props, ref) => {
    const index = useIndex(props.index);
    const array = useArray();
    const field = useField();
    const prefixCls = usePrefixCls("formily-array-base");
    if (!array) return null;
    if (array.field?.pattern !== "editable" || field.pattern !== "editable")
        return null;
    return (
        <UpOutlined
            {...props}
            className={cls(`${prefixCls}-move-up`, props.className)}
            ref={ref}
            onClick={(e) => {
                if (array.props?.disabled) return;
                e.stopPropagation();
                array?.field?.moveUp(index);
                array?.props?.onMoveUp?.(index);
                if (props?.onClick) {
                    props.onClick(e);
                }
                // 添加一个动态的绑定方法
                if (props?.onLogic) {
                    props?.onLogic && props?.onLogic?.(e);
                }
            }}
        />
    );
});

ArrayBase.useArray = useArray;
ArrayBase.useIndex = useIndex;
ArrayBase.mixin = (target: any) => {
    target.Index = ArrayBase.Index;
    target.SortHandle = ArrayBase.SortHandle;
    target.Addition = ArrayBase.Addition;
    target.Remove = ArrayBase.Remove;
    target.Delete = ArrayBase.Delete;
    target.MoveDown = ArrayBase.MoveDown;
    target.MoveUp = ArrayBase.MoveUp;
    target.EditOut = ArrayBase.EditOut;
    target.Detail = ArrayBase.Detail;
    target.Upload = ArrayBase.Upload;
    target.DownOut = ArrayBase.DownOut;
    target.Copy = ArrayBase.Copy;
    target.Export = ArrayBase.Export;
    target.OpenLib = ArrayBase.OpenLib;
    target.Preview = ArrayBase.Preview;
    target.useArray = ArrayBase.useArray;
    target.useIndex = ArrayBase.useIndex;
    target.SalerWtdwl = ArrayBase.SalerWtdwl;
    return target;
};

export default ArrayBase;
